﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Text;
using System.Collections.Generic;
using System.Collections;
using System.Data.SqlClient;
using System.Threading;
using Microsoft.VisualBasic;
using System.Net;
using FluorineFx.Json;
using System.Collections.Specialized;
using NVelocity.App;
using NVelocity.Context;
using NVelocity;



namespace lxwmvc
{
    public class pagebase
    {
        private static VelocityEngine velocity = null;
        private IContext context = null;
        private bool _cancelview = false;
        private bool _cancellayout = false;
        private bool _exit = false;

        private string layoutname = "";
        private string _viewname = "";

        //是这部分的问题吗？
        string defaultcontroller = ConfigurationManager.AppSettings["defaultcontroller"];
        string defaultaction = ConfigurationManager.AppSettings["defaultaction"];

        /// <summary>
        /// 线程安全
        /// </summary>
        readonly static object[] syn = new object[0] { };

        /// <summary>
        /// 同步方法
        /// </summary>
        public static object m_monitorObject = new object();
        static Mutex m_mutex = new Mutex();//全局阻塞

        /// <summary>
        /// 不使用模板，其实在系统中，如果没有模板，系统也不会出现错误，他会自动不显示模板
        /// </summary>
        public void cancelview()
        {
            _cancelview = true;
        }

        /// <summary>
        /// 默认输出json对象
        /// </summary>
        object _JSON = null;
        /// <summary>
        /// 输出json对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T JSON<T>(){
            return (T)_JSON;
        }
        /// <summary>
        /// 输出到界面里面
        /// </summary>
        DictionaryEx<string, object> data = new DictionaryEx<string, object>();
        /// <summary>
        /// 插入page数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public object this[string key]
        {
            get
            {
                if (data.ContainsKey(key))
                    return data[key];
                return "";
            }
            set
            {
                data[key] = value;
            }
        }

        /// <summary>
        /// 退出程序，后续不要再进行操作。
        /// </summary>
        public void exit()
        {
            _exit = true;
            throw new Exception("MMM:人工终止操作！");
        }


        /// <summary>
        /// 改变vm名称
        /// </summary>
        /// <param name="vm">不能带后缀 .htm</param>
        public void randerview(string vm)
        {
            //不能带后缀
            _viewname = vm;
        }

        /// <summary>
        /// 加载layout
        /// </summary>
        /// <param name="vm"></param>
        public void setlayout(string layout)
        {
            //重新设置layout
            layoutname = layout;
        }

        /// <summary>
        /// 不使用布局
        /// </summary>
        public void cancellayout()
        {
            _cancellayout = true;
        }

        string strcontroller = string.Empty;
        string straction = string.Empty;

        /// <summary>
        /// 加入helper
        /// xxxhelper
        /// </summary>
        /// <param name="_t"></param>
        public void addhelper(Type t)
        {
            var name = t.Name;
            var _instance = t.Assembly.CreateInstance(name, false);
            this[name.Split('.')[name.Split('.').Length - 1].ToLower()] = _instance;
        }

        /// <summary>
        /// 外部执行内部方法 20121025
        /// </summary>
        /// <param name="fun"></param>
        /// <param name="arg"></param>
        /// <returns></returns>
        public string customfun(string fun, params object[] arg)
        {
            if (currenttype == null) return "";
            var currentmethod_ = getmethod(currenttype, fun);

            if (currentmethod_ == null) return "";
            if (arg == null || arg.Length == 0)
                currentmethod_.Invoke(null, new object[] { this });
            else
                currentmethod_.Invoke(null, new object[] { this, arg });

            return "";
        }

        /// <summary>
        /// 通过pagebase 获取数据对象
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="qianzhun"></param>
        /// <returns></returns>
        public supermodel model(string tablename = "", string qianzhun = "")
        {
            supermodel has = supermodel.create(tablename);
            var arrs = new List<NameValueCollection>();
            if (Post) arrs.Add(Request.Form);
            arrs.Add(Request.QueryString);

            foreach (NameValueCollection Params in arrs)
            {
                foreach (string s in Params.Keys)
                {
                    if (!string.IsNullOrEmpty(s))//&& !s.Equals(key, StringComparison.OrdinalIgnoreCase))
                    {
                        if (qianzhun == "")
                            has[s.ToLower()] = getonevalue(s);
                        else
                        {
                            if (s.ToLower().StartsWith(qianzhun.ToLower()))
                            {
                                string key = s.Substring(qianzhun.Length).ToLower();
                                if (key.StartsWith(".") || key.StartsWith("_") || key.StartsWith(">")) key = key.Substring(1);//如果是._> 直接去除
                                has[key] = getonevalue(s);
                            }
                        }
                    }
                }
            }

            //特殊处理一下checkbox 等于on的情况
            string keys = v_s("_lxw_column_checkbox_").ToLower();
            foreach (string s in keys.Split(','))
            {
                if (s.Length == 0) continue;
                if (has.ContainsKey(s))  //这里是写死了，如果允许，就是1，不允许就是0，只有两种状态，是否允许再数据库中配置一下？
                    has[s] = has[s].tostr() == "on" ? 1 : 0;
                else
                    has[s] = 0;
            }

            return has;
        }

        /// <summary>
        /// 可能再次使用
        /// </summary>
        Type currenttype = null;
        int _StatusCode = (int)HttpStatusCode.OK;
        /// <summary>
        /// 
        /// </summary>
        public int StatusCode
        {
            set { _StatusCode = value; }
            //这个其实一般不用，先开放也可以
            get { return _StatusCode; }
        }


        /// <summary>
        /// 页面加载核心函数
        /// </summary>
        /// <param name="_context"></param>
        public void execute(HttpContext _context)
        {
            try
            {
                //Request.ContentEncoding = Encoding.UTF8;
                Request = _context.Request;
                Response = _context.Response;
                Session = _context.Session;

                strcontroller = _context.Items["_controller_"].ToString();
                straction = _context.Items["_action_"].ToString();

                if (strcontroller == "_defaultcontroller_") strcontroller = defaultcontroller;
                if (straction == "_defaultaction_") straction = defaultaction;

                _viewname = straction;
                MethodInfo currentmethod = null;
                //这里可能会存在问题
                currenttype = Type.GetType("lxwmvc." + strcontroller + "controller,lxwmvcdll");
                currentmethod = getmethod(currenttype, straction, ref straction);
                //得到真实的
                _viewname = straction;
                //真实的action名称
                if (currentmethod != null)
                {
                    straction = currentmethod.Name.ToLower();
                    context = new VelocityContext();
                }

                //List<Attribute> controllerattribute = new List<Attribute>();
                List<Attribute> actionattribute = new List<Attribute>();
                if (currentmethod != null)
                {
                    object[] attrs = currentmethod.GetCustomAttributes(false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        foreach (var o in attrs)
                        {
                            actionattribute.Add(o as Attribute);
                        }
                    }
                }

                if (currenttype != null)
                {
                    object[] attrs = currenttype.GetCustomAttributes(false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        foreach (var o in attrs)
                        {
                            actionattribute.Add(o as Attribute);
                        }
                    }
                }

                //查找事务
                var trans = actionattribute.Find(o => o.GetType() == typeof(transAttribute));
                if (trans != null) sqlhelper.starttranscation(trans);

                var _init = getmethod(currenttype, "_init");
                //这句话非常重要
                if (_init != null) _init.Invoke(null, new object[] { this });

                var json = actionattribute.Find(o => o.GetType() == typeof(jsonAttribute));
                Type jsontype = null;
                if (currentmethod != null)
                {
                    if (json != null)
                    {
                        jsontype = ((jsonAttribute)json).jsontype;
                        _JSON = jsontype.Assembly.CreateInstance(jsontype.FullName);
                    }

                    Response.StatusCode = _StatusCode;
                    var lc = actionattribute.FindAll(o => o.GetType() == typeof(tongbuAttribute));
                    if (lc == null || lc.Count == 0)
                        currentmethod.Invoke(null, new object[] { this });
                    else
                    {
                        try
                        {
                            //加方法锁
                            m_mutex.WaitOne();
                            currentmethod.Invoke(null, new object[] { this });
                        }
                        finally
                        {
                            m_mutex.ReleaseMutex();
                        }

                    }
                }
                else
                {
                    Response.StatusCode = (int)HttpStatusCode.NotFound;
                }

                //输出json对象
                if (json != null)
                {
                    Response.ContentType = "application/json";

                    var jsonString = JavaScriptConvert.SerializeObject(_JSON);
                    string p = @"new Date\((\d+)\)";
                    MatchEvaluator matchEvaluator = new MatchEvaluator(ConvertJsonDateToDateString);
                    Regex reg = new Regex(p);
                    jsonString = reg.Replace(jsonString, matchEvaluator);
                    Response.Write(
                        jsonString
                    );
                }
                else
                {
                    //如果不设置，是直接加载layout的
                    if (!_cancellayout)
                    {
                        //找方法上的
                        var layout = actionattribute.Find(o => o.GetType() == typeof(layoutAttribute));
                        if (layout != null)
                        {
                            layoutname = (layout as layoutAttribute).layoutname;
                        }
                    }

                    //输出helper信息
                    var helpers = actionattribute.FindAll(o => o.GetType() == typeof(helperAttribute));
                    foreach (helperAttribute o in helpers)
                    {
                        if (this.context.ContainsKey(o.helpertype.Name.ToLower())) continue;
                        this[o.helpertype.Name.ToLower()] = o.instance;
                    }


                    //把日期输出去
                    this["now"] = DateTime.Now;
                    this["this"] = this;

                    //把request输出出去
                    foreach (string s in Request.QueryString.Keys)
                    {
                        //如果已经存在，就不要输出出去了。
                        if (!context.ContainsKey(s))
                            this[s] = Request.QueryString[s];
                    }

                    //把全局helper压缩出去
                    this["globalhelper"] = new globalhelper();
                    //this["formhelper"] = new formhelper();
                    this["funhelper"] = new funhelper();
                    this["jiandansql"] = new jiandansql();
                    this["stringhelper"] = new stringhelper();
                    this["request"] = Request;

                    try
                    {
                        this["config_qiyemingcheng"] = System.Configuration.ConfigurationManager.AppSettings["config_qiyemingcheng"].ToString();
                    }
                    catch { }

                    //随机数
                    this["random"] = "__i=" + Guid.NewGuid().ToString();
                    //把这个替换成$
                    this["_JQ_"] = "$";
                    //如果没有设置，系统默认设置这个值
                    if (!context.ContainsKey("formurl"))
                        this["formurl"] = requesthelper.formurl();

                    //QueryString
                    //this["querystring"] = Request.QueryString.ToString();

                    //显示模板
                    //如果是单表操作

                    if (_viewname.IndexOf("\\") != -1 || _viewname.IndexOf("/") != -1)
                    {
                        //不能带后缀
                        display(_viewname);
                    }
                    else
                    {
                        if (table.Length > 0 && strcontroller == "table")
                            display(table + "\\" + _viewname + ".htm");
                        else
                            display(strcontroller + "\\" + _viewname + ".htm");
                    }                    
                }
                //统一提交事务
                sqlhelper.transactioncommit();
            }
            //[System.Threading.ThreadAbortException] = {由于代码已经过优化或者本机框架位于调用堆栈之上，无法计算表达式的值。}
            catch (ThreadAbortException)
            {
                Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                Console.Write("ThreadAbortException");
            }
            catch (Exception err)
            {
                sqlhelper.transactionrollback();
                //错误信息
                Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                throw err;
            }
            finally
            {
                //释放session
                sqlhelper.dbconnectclose();
                //Session.Remove(sqlhelper.has_transaction);
                //Session.Remove(sqlhelper.lxw_transaction);
                //Session.Remove(sqlhelper.context_connect);
            }
        }

        //public string encodejscript(string strJsMsg)
        //{
        //    Regex re = new Regex("\\\\|\\\"|\\\r|\\\n|\\\'|\\<|\\>|\\&", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
        //    return re.Replace(strJsMsg, new MatchEvaluator(encodejscript));
        //}

        string ConvertJsonDateToDateString(Match m)
        {
            string result = string.Empty;
            DateTime dt = new DateTime(1970, 1, 1);
            dt = dt.AddMilliseconds(long.Parse(m.Groups[1].Value));
            dt = dt.ToLocalTime();
            result = dt.ToString("yyyy-MM-dd HH:mm:ss");
            return "\""+result+"\"";
        }

        //string encodejscript(Match m)
        //{
        //    int code = (int)m.Value[0];
        //    string chars = "0123456789ABCDEF";
        //    int a1 = code & 0xF;
        //    int a2 = (code & 0xF0) / 0x10;
        //    return "\\x" + chars[a2] + chars[a1];
        //}

        //public string writelog(Exception lastException)
        //{
        //    //StringBuilder sb = new StringBuilder();
        //    //writeerrorlog(sb, lastException);

        //    //return writelog(sb.ToString());
        //    return "";
        //}

        /// <summary>
        /// 得到方法体,也可以通过别名找
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="truename"></param>
        /// <returns></returns>
        MethodInfo getmethod(Type type, string name, ref string truename)
        {
            MethodInfo[] ms = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
            foreach (MethodInfo m in ms)
            {
                string bieming = m.Name;
                {
                    object[] attrs = m.GetCustomAttributes(typeof(biemingAttribute), false);
                    if (attrs != null && attrs.Length > 0)
                    {
                        bieming = (attrs[0] as biemingAttribute).bieming;
                    }
                }

                //忽略大小写
                if (bieming.Trim().Equals(name.Trim(), StringComparison.OrdinalIgnoreCase))
                {
                    //别名作为新的vm文件
                    //_viewname = bieming.Trim();
                    truename = bieming.Trim();
                    return m;
                }
            }

            return null;
        }

        MethodInfo getmethod(Type type, string name)
        {
            return getmethod(type, name, ref name);
        }

        /// <summary>
        /// 没有值，或者转换失败，都用-1代替，也可以自己设置
        /// </summary>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <returns></returns>
        public int v_i(string key, int def = -1)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    return def;
                }

                return value.toint32(def);
            }
            catch
            {
                return def;
            }
        }

        /// <summary>
        /// 获取字符串信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string v_s(string key)
        {
            string value = getonevalue(key);
            sqlvalidator.checkstring(value);
            if (value == null)
            {
                return "";
            }

            return value;
        }

        /// <summary>
        /// 获取安全的字符串
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string v_ss(string key)
        {
            string value = getonevalue(key);
            if (value == null)
            {
                return "";
            }

            return value.Replace("'", "''").Split(';')[0];
        }

        /// <summary>
        /// 获取decimal对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public decimal v_dec(string key)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                    return 0m;
                }

                return Convert.ToDecimal(value);
            }
            catch
            {
                return 0m;
            }
        }

        /// <summary>
        /// 获取日期对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public DateTime v_date(string key)
        {
            string value = getonevalue(key);
            try
            {
                if (value == null)
                {
                    //writelog("无法取到Request.Params[\"{0}\"]的数据!", key);
                    return new DateTime(1900, 1, 1);
                }

                return Convert.ToDateTime(value);
            }
            catch
            {
                return new DateTime(1900, 1, 1);
            }
        }

        /// <summary>
        /// 获取前台传递过来的数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public string getonevalue(string key)
        {
            string v = "";
            if (Post)
            {
                //如果查询，直接定位到第一页。
                if (key.ToLower() == "page") return "0";
                v = Request.Form[key];
                if (v == null)
                {
                    v = Request.QueryString[key]??"";
                }
            }
            else
            {
                v = Request.QueryString[key]??"";
            }

            return v;
        }


        /// <summary>
        /// 输出信息
        /// </summary>
        /// <param name="p"></param>
        /// <param name="arg"></param>
        public void write(string p, params object[] arg)
        {
            Response.ContentType = "text/html";
            if (arg != null && arg.Length > 0)
                p = string.Format(p, arg);
            Response.Write(p);
        }

        /// <summary>
        /// 判断是否为POST请求
        /// </summary>
        public bool Post
        {
            get
            {
                return Request.HttpMethod.ToUpper() == "POST";
            }
        }

        /// <summary>
        /// 获取页面传输过来的json对象
        /// </summary>
        public JavaScriptObject bodyjson()
        {
            StreamReader sb = new StreamReader(Request.InputStream, Encoding.UTF8);
            var content = sb.ReadToEnd();

            JavaScriptObject o2 = JavaScriptConvert.DeserializeObject(
                content
                ) as JavaScriptObject;

            return o2;
        }

        /// <summary>
        /// Request
        /// </summary>
        public HttpRequest Request { get; set; }
        /// <summary>
        /// Response
        /// </summary>
        public HttpResponse Response { get; set; }
        /// <summary>
        /// Session
        /// </summary>
        public System.Web.SessionState.HttpSessionState Session { get; set; }
    }

    /// <summary>
    /// ExitException
    /// </summary>
    public class ExitException : Exception
    {
        /// <summary>
        /// ExitException
        /// </summary>
        public ExitException() : base() { }
    }
}